iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
ChatGPT & Codex

從零開始,用 ChatGPT 與 Codex 打造我的泰語小旅伴系列 第 9

Day 9|第一次讓 App 真的可以操作:基本問候課程

  • 分享至 

  • xImage
  •  

昨天終於在 lessons.js 建立了第一份泰語教材,包含你好、謝謝、對不起和再見四句基本問候。

不過,光是把教材放進檔案裡,使用者還是沒辦法直接學習。

目前的首頁雖然已經有五張情境課程卡片,但它們都還只是靜態畫面。就算看到「基本問候」,也還不能真的點進去學習。

所以今天要解決的問題很明確:

讓使用者可以從首頁進入基本問候課程,看到四句泰語,再返回首頁。

這也是「泰語小旅伴」第一次真正加入課程互動功能。

先別急著做五個課程

前面 Day 2 已經規劃了五個旅遊情境,包括基本問候、購物、餐廳點餐、咖啡店和交通問路。

但現在如果一次把五個課程都做出來,對完全不熟悉 JavaScript 的我來說,可能會一下子多出太多需要理解和驗收的內容。

所以這次先選擇「基本問候」,利用已經準備好的四句教材,專心處理使用者怎麼看到它們。

和 ChatGPT 討論後,我們先把這次的目標整理成三件事:

  1. 點擊首頁的「基本問候」,可以進入課程。
  2. 課程畫面要正確顯示四句教材。
  3. 點擊返回按鈕,可以回到首頁。

暫時不加入發音、測驗和學習紀錄。

這樣做完之後,我至少知道自己該檢查哪些功能,而不是看到 Codex 說完成,就不知道接下來該做什麼。

點了基本問候之後,應該發生什麼事?

在 Day 6 製作首頁時,我們主要調整的是 HTML 和 CSS,當時的目標是讓畫面看起來更像手機 App,還沒有要求課程卡片真的能操作。

但今天不一樣了。

使用者按下「基本問候」之後,App 需要顯示另一個畫面,並把前一天建立的教材呈現出來。

我先把這件事理解成:

首頁
  ↓
點擊「基本問候」
  ↓
顯示基本問候課程
  ↓
看到四句教材
  ↓
點擊「返回首頁」
  ↓
回到首頁

看起來只有幾個步驟,但它已經不只是把文字放在網頁上,而是要讓畫面根據使用者的操作產生變化。

這時候,Day 4 認識的 JavaScript 終於開始派上用場。

把任務交給 Codex

討論清楚之後,就把需求交給 Codex 實作。

這次的要求包括讓「基本問候」可以點擊、顯示四句教材,以及提供返回首頁的操作。

另外,教材內容要使用前面建立的 data/lessons.js,而不是重新把四句泰語寫進 HTML。

根據開發紀錄,這一輪總共修改四個檔案:

index.html
css/style.css
data/lessons.js
js/app.js

這裡補充一下:這四個檔案其實是在同一輪實作中修改的。昨天的 Day 8 先介紹教材資料的建立,今天則接著理解同一輪實作中的課程互動部分。

透過這次修改,我開始看到不同檔案怎麼互相配合。

lessons.js 負責保存教材,app.js 負責處理課程切換與教材呈現,而 HTML 和 CSS 則提供畫面結構與樣式。

原本分開存在專案裡的檔案,現在開始一起完成同一個功能了。

原來教材卡片可以由 JavaScript 產生

這次有個地方讓我開始理解,為什麼前一天要先把教材獨立出來。

因為教材已經放在 lessons.js,JavaScript 就可以使用這些資料,產生畫面上的教材卡片,不需要在 HTML 裡重新保存一份相同的內容。

Codex 在 app.js 裡建立了一個函式:

// 根據一筆教材資料建立一張句子卡片。
function createPhraseCard(phrase) {
  const card = document.createElement("article");
  const chinese = document.createElement("h3");
  const thai = document.createElement("p");
  const pronunciation = document.createElement("p");

  card.className = "phrase-card";
  chinese.className = "phrase-chinese";
  thai.className = "phrase-thai";
  pronunciation.className = "phrase-pronunciation";

  chinese.textContent = phrase.chinese;
  thai.textContent = phrase.thai;
  thai.lang = "th";
  pronunciation.textContent = phrase.pronunciation;

  card.append(chinese, thai, pronunciation);

  return card;
}

第一次看到這段程式,我還沒辦法完全理解每一行,但可以先從它的目的開始看。

createPhraseCard() 的工作,是根據一筆教材資料,建立一張顯示句子的卡片。

其中,document.createElement() 可以用來建立 HTML 元素。

例如:

const card = document.createElement("article");

就是建立一個 article 元素,準備用來當作教材卡片。

接著,程式透過 textContent,把教材資料填入對應的位置:

chinese.textContent = phrase.chinese;
thai.textContent = phrase.thai;
pronunciation.textContent = phrase.pronunciation;

這三行對應的就是中文、泰文和羅馬拼音。

例如 phrase.thai 會取得教材資料中的泰文字串,再放進畫面上的泰文元素。

最後,程式把這些元素組合成一張卡片:

card.append(chinese, thai, pronunciation);

對現在的我來說,可以先把整段程式理解成:

拿到一筆教材 → 建立卡片 → 填入中文、泰文和拼音 → 把卡片交回去使用。

這比直接把四句教材都寫死在 HTML 裡,更能讓我理解前一天討論的資料與畫面分離。

四句教材是怎麼出現在畫面上的?

建立好單張教材卡片後,接下來還需要把整個課程顯示出來。

Codex 在 app.js 裡寫了另一個函式:

// 顯示基本問候課程,並把 lessons.js 的教材放進畫面。
function showBasicGreetingsLesson() {
  const lesson = lessons.basicGreetings;

  lessonTitle.textContent = lesson.title;
  phraseList.replaceChildren();

  lesson.phrases.forEach(function (phrase) {
    phraseList.append(createPhraseCard(phrase));
  });

  homeView.hidden = true;
  bottomNav.hidden = true;
  lessonView.hidden = false;
}

這段程式雖然比前面多了一些新語法,但拆開來看,還是能慢慢理解。

首先:

const lesson = lessons.basicGreetings;

這行會從 lessons.js 的教材資料中,取得基本問候課程。

接著:

lessonTitle.textContent = lesson.title;
phraseList.replaceChildren();

第一行負責設定課程標題,第二行則是先清空原本的教材列表。

為什麼要先清空?

因為接下來會重新產生教材卡片,先清空列表,就能避免重複加入原本的內容。

而真正把四句教材顯示出來的關鍵,是這段:

lesson.phrases.forEach(function (phrase) {
  phraseList.append(createPhraseCard(phrase));
});

forEach() 可以先理解成:針對陣列裡的每一筆資料,依序執行指定的工作。

我們的基本問候課程有四句教材,所以程式就會依序取得四筆資料,每次呼叫 createPhraseCard() 建立一張卡片,再把卡片放進教材列表。

這也是我第一次透過自己的 App,看到 JavaScript 的陣列不只是保存資料,還可以讓程式用相同的方式處理多筆內容。

不用為了「你好」、「謝謝」、「對不起」和「再見」,各自寫一套不同的卡片產生程式。

原來切換畫面,可以先從 hidden 開始

教材準備好之後,還需要讓使用者看到課程畫面。

showBasicGreetingsLesson() 的最後,Codex 寫了:

homeView.hidden = true;
bottomNav.hidden = true;
lessonView.hidden = false;

這裡的 hidden 可以先理解成控制 HTML 元素是否隱藏的屬性。

設定成 true,代表把對應元素隱藏;設定成 false,則代表取消隱藏。

所以這三行的意思就是:

把首頁藏起來、把底部導覽藏起來,再顯示課程畫面。

對現在的我來說,這種做法比想像中容易理解。

原來這次不是重新開啟另一個網頁,而是在同一個頁面裡,控制哪些區域要顯示、哪些區域要隱藏。

不過,要讓它真的可以操作,還需要把這個函式和首頁按鈕連接起來。

點擊按鈕,JavaScript 才知道要做什麼

根據 Codex 的紀錄,首頁的「基本問候」已經改成真正的 HTML button 元素。

而在 JavaScript 裡,則透過這一行把按鈕和功能連接起來:

basicGreetingsButton.addEventListener("click", showBasicGreetingsLesson);

addEventListener() 可以先理解成:告訴程式,要留意某個元素發生了什麼事件。

這裡的 "click" 就是點擊事件。

當使用者點擊「基本問候」按鈕時,程式就會執行 showBasicGreetingsLesson(),進入剛才介紹的課程畫面。

那返回首頁呢?

Codex 另外寫了一個函式:

// 隱藏課程畫面並回到原本首頁。
function showHome() {
  lessonView.hidden = true;
  homeView.hidden = false;
  bottomNav.hidden = false;
}

它和進入課程的邏輯剛好相反。

把課程畫面藏起來,再把首頁和底部導覽顯示出來。

最後,再把返回按鈕接上這個函式:

backButton.addEventListener("click", showHome);

這樣一來,今天規劃的操作流程就完整了。

使用者可以從首頁進入基本問候課程,看完四句教材後,再返回首頁。

而且這次沒有把點擊處理直接寫成 HTML 裡的 inline onclick,而是把事件處理放在 app.js 中。

這也讓我再次看到,HTML 和 JavaScript 可以分開負責不同的事情。

Codex 做完之後,先看測試結果

功能完成後,Codex 回報已經進行測試。

根據當時的開發紀錄,測試結果包括:

  • 可以成功進入基本問候課程。
  • 正確顯示四句教材。
  • 可以成功返回首頁。
  • Console 沒有出現錯誤或警告。

此外,Codex 也確認 lessons.js 會在 app.js 之前載入,讓處理課程的程式能取得教材資料。

但這次新增的是互動功能,還是需要實際操作,才能確認整個流程是否符合原本的需求。

因此,Codex 的測試完成後,接下來就是我自己的驗收。

換我自己實際操作看看

我在自己的瀏覽器打開「泰語小旅伴」,從首頁點擊「基本問候」,確認可以進入課程畫面。

接著檢查四句教材是否正常顯示,包括你好、謝謝、對不起和再見。

最後再點擊返回首頁,確認可以順利回到原本的畫面。

這三個操作都正常。

因此,這次不只有 Codex 的測試回報,也有我自己實際操作的驗收結果。

不過,驗收成功的範圍仍然需要分清楚。

目前確認的是基本問候課程可以進入、教材可以顯示,以及返回首頁的功能正常。

這不代表其他四個情境課程已經可以使用,也不代表發音、測驗或學習進度已經完成。

至少第一個課程,終於真的可以操作了。

完成之後,先保存版本

還記得 Day 7 第一次使用 Git,就是希望能保存已經確認正常的開發階段。

這次完成基本問候課程後,Codex 也建立了第二個 commit:

f8eb6b5
feat: add basic greetings lesson

這個版本包含基本問候的教材和課程互動功能。

也就是說,目前已經有兩個明確的開發階段:

3ddd34e
第一版靜態首頁

    ↓

f8eb6b5
加入基本問候課程

這也讓昨天建立的版本保存流程,開始真正用在後續功能開發中。

每完成一個範圍明確的功能,經過測試與驗收之後,再保存一個版本,就比較容易知道每一次修改到底增加了什麼。

今天學到什麼?

今天終於讓「泰語小旅伴」從只有靜態首頁,變成有第一個可以操作的課程。

原本只是顯示在首頁上的「基本問候」,現在已經可以點進去,看到四句泰語,再返回首頁。

透過這次實作,我也開始理解 HTML、CSS、JavaScript 和教材資料是怎麼一起工作的。

HTML 提供畫面結構,CSS 負責外觀,lessons.js 保存教材,而 app.js 則讓使用者的操作和教材資料真正連接起來。

這次也第一次透過自己的專案接觸到 createElement()forEach()hiddenaddEventListener() 這些 JavaScript 用法。

雖然我還沒有完全理解所有語法,但至少已經知道這次的程式要完成什麼,以及該怎麼檢查它有沒有正常運作。

和第一次只有一張歡迎畫面的網頁相比,現在的「泰語小旅伴」終於開始有了真正的學習功能。

不過,還有一個很重要的功能沒做。

現在使用者可以看到泰文和羅馬拼音,但如果完全不會泰語,光看文字還是不容易知道該怎麼發音。

能不能讓使用者按一下按鈕,就直接聽到泰語?

下一篇,就來研究瀏覽器的 Web Speech API,讓「泰語小旅伴」第一次真正開口說泰語。


上一篇
Day 8|不把教材寫死在 HTML:建立第一份泰語課程資料
系列文
從零開始,用 ChatGPT 與 Codex 打造我的泰語小旅伴9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言